home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-08-23 | 34.0 KB | 1,302 lines | [TEXT/MPS ] |
- // Copyright ©1994 Apple Computer, Inc.
- // Author: John Powers
- // Date: 27-Aug-94
-
- // UApp.cp
- // The derived application class.
- // The TApplication and TDocument folders
- // have been left unchanged from the developer CD.
- // Our use of the application is tailored in the classes below.
-
- #ifndef __UAPP__
- #include "UApp.h"
- #endif
-
- #if __WantMoGuide__
- #ifndef __UAPPMO__
- #include "UAppMo.h"
- #endif
- #endif
-
- Boolean gAGuideAvailable;
-
- // Segment
-
- #pragma segment Main
-
- // =========================================================================
- // main
- // ---------------------------------------------------------------------
- // main
- // Application entry point.
- // It all starts here.
- // If we need it, we can make ourApp global.
- int
- main()
- {
- #if __WantMoGuide__
- TAppMo* ourApp = new TAppMo;
- #else
- TApp* ourApp = new TApp;
- #endif
- if(!ourApp)
- {
- return 0;
- }
- // Do basic initialization, then wait in
- // the event loop for the startup event.
- if(ourApp->Init()==noErr)
- {
- ourApp->EventLoop();
- ourApp->Quit();
- }
- return 0;
- }
-
- // ------------------------------------------------------------------------
- // AlertIfError
- // Display an alert if an error code is passed.
- // Return the error code.
- OSErr
- AlertIfError(OSErr err)
- {
- if(err!=noErr)
- {
- DialogPtr pDlog;
- GrafPtr pOldPort;
- Boolean isShowing=true;
- GetPort(&pOldPort);
- pDlog = GetNewDialog(kAlertIfErrorDialogID, nil, FRONT_WINDOW);
- if(pDlog)
- {
- Handle hDItem;
- short itemType;
- Rect itemRect;
- Str255 textStr;
- // Error number
- NumToString(err, textStr);
- GetDItem(pDlog, kAlertIfErrorErrNum, &itemType, &hDItem, &itemRect);
- SetIText(hDItem, textStr);
- // Show dialog.
- CenterWindow(pDlog);
- SetPort(pDlog);
- ShowWindow(pDlog);
- // Draw default outline around OK button.
- GetDItem(pDlog, kAlertIfErrorOK, &itemType, &hDItem, &itemRect);
- PenSize(3,3);
- InsetRect(&itemRect, -4, -4);
- FrameRoundRect(&itemRect, 16, 16);
- PenNormal();
- // Let user read.
- short itemHit;
- while (isShowing) {
- ModalDialog(nil, &itemHit);
- isShowing = itemHit!=kAlertIfErrorOK;
- }
- DisposeDialog(pDlog);
- }
- SetPort(pOldPort);
- }
- return err;
- }
-
- // ------------------------------------------------------------------------
- // CenterWindow
- //
- void
- CenterWindow(WindowPtr pWin)
- {
- Point windowLoc;
- Rect boundsRect;
- GetWindowBounds(pWin, &boundsRect);
- short windowHeight = pWin->portRect.bottom - pWin->portRect.top;
- short windowWidth = pWin->portRect.right - pWin->portRect.left;
- short boundsHeight = boundsRect.bottom - boundsRect.top;
- short boundsWidth = boundsRect.right - boundsRect.left;
- windowLoc.v = boundsRect.top + ((boundsHeight - windowHeight) / 2);
- windowLoc.h = boundsRect.left + ((boundsWidth - windowWidth) / 2);
- MoveWindow(pWin, windowLoc.h, windowLoc.v, false);
- }
-
- // ------------------------------------------------------------------------
- // GetWindowBounds
- // Get the bounds for the window.
- // The menubar is excluded from the main device bounds.
- // If the window overlaps devices, use the smallest device
- // for the window top and bottom bounds.
- //
- void
- GetWindowBounds(WindowPtr pWin, Rect* pBoundsRect)
- {
- // See if we have Color QuickDraw.
- SysEnvRec sysEnv;
- SysEnvirons( curSysEnvVers, &sysEnv );
- if (!sysEnv.hasColorQD)
- *pBoundsRect = qd.screenBits.bounds;
- else
- {
- typedef union {
- Rect rect;
- struct {
- Point topleft;
- Point botright;
- } corner;
- } GlobRect;
- Rect deviceRect;
- GlobRect windowRect;
- Rect overlapRect;
- GDHandle hGD;
- GDHandle hGDMain = GetMainDevice();
- GrafPtr savePort;
- // Get our window's rectangle in global coordinates.
- windowRect.rect = pWin->portRect;
- GetPort(&savePort);
- SetPort(pWin);
- LocalToGlobal(&windowRect.corner.topleft);
- LocalToGlobal(&windowRect.corner.botright);
- // Initialize *pBoundsRect.
- *pBoundsRect = (*GetGrayRgn())->rgnBBox;
- // Loop to examine each device for overlap with our window.
- for (hGD = GetDeviceList(); hGD; hGD = GetNextDevice(hGD))
- {
- // Look for active screen device.
- if (TestDeviceAttribute(hGD, screenDevice))
- {
- if (TestDeviceAttribute(hGD, screenActive))
- {
- deviceRect = (**hGD).gdRect; // global bounds of device.
- // Check for overlap of device and window.
- if (SectRect(&deviceRect, &windowRect.rect, &overlapRect))
- {
- // We have overlap; if main device, exclude menubar.
- if(hGD==hGDMain)
- {
- deviceRect.top += GetMBarHeight();
- } // if(hGD…
- // Set top and bottom bounds for window.
- if(pBoundsRect->top < deviceRect.top)
- pBoundsRect->top = deviceRect.top;
- if(pBoundsRect->bottom > deviceRect.bottom)
- pBoundsRect->bottom = deviceRect.bottom;
-
- // clip left and right to left and right side of screens on which
- // the window resides
-
- if ( windowRect.rect.left > deviceRect.left &&
- pBoundsRect->left < deviceRect.left )
- {
- pBoundsRect->left = deviceRect.left;
- }
- if ( windowRect.rect.right < deviceRect.right &&
- pBoundsRect->right > deviceRect.right )
- {
- pBoundsRect->right = deviceRect.right;
- }
-
- } // if(SectRect…
- } // if(TestDeviceAttribute…
- } // if(TestDeviceAttribute…
- } // for(hGD…
- SetPort(savePort);
- }
- };
-
- // ------------------------------------------------------------------------
- // TApp::HandleAECore
- // Handles the core events.
- // Comes from the Finder after our application is launched.
- // When we are launched, we initialize and then wait for a core event.
- // The kAEOpenApplication or kAEOpenDocuments event starts the action!
- // The refCon contains our application object.
- // Should be in a locked, unpurgeable segment.
- //
- // Unfortunately, the DTS sample TApplication does not process
- // high level events. We fix that by overriding the EventLoop
- // and adding high-level event processing.
- //
- pascal OSErr
- TApp::HandleAECore(AppleEvent& theAppleEvent,
- AppleEvent& /*theReply*/, long refCon)
- {
- OSType eventId;
- Size actualSize;
- DescType returnedType;
- AEKeyword theAEKeyword;
- OSErr err=noErr;
- AEDescList docList;
- long docCnt;
- FSSpec fileSpec;
- TApp* ourApp=(TApp*)refCon;
- // Useless without our application object.
- if(!ourApp)
- return kErrNoAppObject;
- // A core event, get event id.
- err = AEGetAttributePtr(&theAppleEvent, keyEventIDAttr,
- typeType, &returnedType,
- (Ptr) &eventId, sizeof(eventId),
- &actualSize);
- switch (eventId)
- {
- case kAEOpenApplication:
- // Startup. Attempt autostart if possible.
- err = ourApp->Start();
- if(err==noErr)
- {
- if(ourApp->fAutoStart)
- {
- // Attempt autostart and get preset database spec.
- err = ourApp->fAutoStart->AttemptAutoStart();
- ourApp->fAutoStart->GetFile(ourApp->fPresetGuideFile);
- if(err!=noErr)
- ourApp->ExitLoop();
- else if(gAGuideAvailable)
- {
- if(AGGetStatus()==kAGIsActive)
- {
- // Did start Apple Guide with a database.
- // Update our database variables.
- ourApp->fAutoStart->GetRefNum(ourApp->fGuideRefNum);
- }
- }
- }
- }
- break;
- case kAEOpenDocuments:
- // Ask Apple Guide to open one document.
- err = AEGetParamDesc(&theAppleEvent, keyDirectObject,
- typeAEList, &docList);
- if(err==noErr)
- {
- err = AECountItems(&docList, &docCnt);
- if(err==noErr && docCnt>0)
- {
- err = AEGetNthPtr(&docList, 1, typeFSS, &theAEKeyword,
- &returnedType, (Ptr) &fileSpec,
- sizeof(fileSpec), &actualSize);
- if(err==noErr)
- {
- err = ourApp->Start();
- if(err==noErr)
- err = ourApp->OpenGuideDatabase(&fileSpec);
- }
- }
- }
- break;
- case kAEPrintDocuments:
- // We're not printing anything.
- break;
- case kAEQuitApplication:
- // All done.
- ourApp->ExitLoop();
- break;
- case kAEAnswer:
- // We're not expecting any replies.
- break;
- default:
- break;
- }
- return err;
-
- }
-
- // Segment
-
- #pragma segment MoG1
-
- // =========================================================================
- // TApp
- // --------------------------------------------------------------------------
- // TApp::AdjustMenus
- //
- void
- TApp::AdjustMenus() // override
- {
- MenuHandle hmFile=GetMHandle(mFile);
- MenuHandle hmEdit=GetMHandle(mEdit);
- // Always avaliable.
- EnableItem(hmFile, iGetInfo);
- EnableItem(hmFile, iQuit);
- EnableItem(hmEdit, iShowClipboard);
- // Set default case.
- DisableItem(hmFile, iOpenFile);
- DisableItem(hmFile, iCloseFile);
- // If Apple Guide is installed,
- // then we can open a guide database.
- if(gAGuideAvailable)
- {
- // Select and open guide database.
- EnableItem(hmFile, iOpenFile);
- // Check to see if our database is open.
- // If it isn't, then set our refNum to nil.
- // If we track the database in our idle loop,
- // we run the risk of a race condition.
- // For example, MoGuide opens a database and
- // the idle checks to see if it's open.
- // Apple Guide opening may not completed opening
- // the database by the time MoGuide's idle loop is executed.
- // So we check it here, right before we need it.
- if(!AGIsDatabaseOpen(this->fGuideRefNum))
- this->fGuideRefNum = nil;
- // If we have a non-nil this->fGuideRefNum,
- // then our database is open. Permit closing.
- if(this->fGuideRefNum)
- EnableItem(hmFile, iCloseFile);
- }
- }
-
- // ------------------------------------------------------------------------
- // TApp::CloseDoc
- //
- // Close the document by a "GoAway" on its document.
- //
- void
- TApp::CloseDoc(TDoc* docToClose)
- {
- if(docToClose)
- {
- // Update current document and window pointer
- // to that which is to be closed.
- this->fCurDoc = docToClose;
- this->fWhichWindow = this->fCurDoc->GetDocWindow();
- SetPort(this->fWhichWindow);
- // Let the "GoAway" handle it.
- this->DoGoAway();
- }
- }
-
- // ------------------------------------------------------------------------
- // TApp::CopyToClipboard
- //
- void
- TApp::CopyToClipboard()
- {
- // There is no trap equivalent for this operation.
- }
-
- // ---------------------------------------------------------------------
- // TApp::DoAbout
- // Display the "About…" box.
- void
- TApp::DoAbout()
- {
- DialogPtr pDlog;
- Str255 versString;
- short itemType;
- Handle hItem;
- Rect box;
- short itemHit;
- GrafPtr savePort;
- // Get dialog.
- pDlog = GetNewDialog(rAboutDlog, kDefaultStorage, (WindowPtr) kInFrontOfAll);
- // Set version informaton.
- GetDItem(pDlog, iAboutTitle, &itemType, &hItem, &box);
- this->GetVersion(versString);
- SetIText(hItem, versString);
- // Add default outline around OK button.
- ShowWindow(pDlog);
- GetDItem(pDlog, iAboutOk, &itemType, &hItem, &box);
- GetPort(&savePort);
- SetPort(pDlog);
- PenSize(3,3);
- InsetRect(&box, -4, -4);
- FrameRoundRect(&box, 16, 16);
- PenNormal();
- SetPort(savePort);
- // Wait for user action.
- ModalDialog(kNoFilterProc, &itemHit);
- // Clean up.
- DisposDialog(pDlog);
- HiliteMenu(0);
- }
-
- // ------------------------------------------------------------------------
- // TApp::DoDBInfoDialog
- void
- TApp::DoDBInfoDialog(FSSpec& guideFileSpec)
- {
- DialogPtr pDlog;
- GrafPtr pOldPort;
- Boolean isShowing=true;
-
- GetPort(&pOldPort);
- pDlog = GetNewDialog(kDBInfoDialogID, nil, FRONT_WINDOW);
- if(pDlog)
- {
- Handle hDItem;
- short itemType;
- Rect itemRect;
- Str255 textStr;
- OSErr err;
- // Database type
- AGFileDBType databaseType;
- err = AGFileGetDBType(&guideFileSpec, &databaseType);
- NumToString((long) databaseType, textStr);
- GetDItem(pDlog, kDBInfoType, &itemType, &hDItem, &itemRect);
- SetIText(hDItem, textStr);
- // Menu item name
- err = AGFileGetDBMenuName(&guideFileSpec, textStr);
- if(err==noErr)
- {
- GetDItem(pDlog, kDBInfoMenu, &itemType, &hDItem, &itemRect);
- SetIText(hDItem, textStr);
- }
- // Selector count
- short selectorCnt = AGFileGetSelectorCount(&guideFileSpec);
- NumToString((long) selectorCnt, textStr);
- GetDItem(pDlog, kDBInfoSelectorCnt, &itemType, &hDItem, &itemRect);
- SetIText(hDItem, textStr);
- AGFileSelectorType selector;
- AGFileSelectorValueType value;
- // Selector #1
- selector = 0;
- err = AGFileGetSelector(&guideFileSpec, 1, &selector, &value);
- if(err==noErr && selector)
- {
- NumToString(value, textStr);
- GetDItem(pDlog, kDBInfoSelector1Value, &itemType, &hDItem, &itemRect);
- SetIText(hDItem, textStr);
- textStr[0] = 4;
- BlockMove(&selector, &textStr[1], 4);
- }
- else
- {
- GetIndString(textStr, kDBInfoStrId, kStrNoInfo);
- }
- GetDItem(pDlog, kDBInfoSelector1, &itemType, &hDItem, &itemRect);
- SetIText(hDItem, textStr);
- // Selector #2
- selector = 0;
- err = AGFileGetSelector(&guideFileSpec, 2, &selector, &value);
- if(err==noErr && selector)
- {
- NumToString(value, textStr);
- GetDItem(pDlog, kDBInfoSelector2Value, &itemType, &hDItem, &itemRect);
- SetIText(hDItem, textStr);
- textStr[0] = 4;
- BlockMove(&selector, &textStr[1], 4);
- }
- else
- {
- GetIndString(textStr, kDBInfoStrId, kStrNoInfo);
- }
- GetDItem(pDlog, kDBInfoSelector2, &itemType, &hDItem, &itemRect);
- SetIText(hDItem, textStr);
- // Selector #3
- selector = 0;
- err = AGFileGetSelector(&guideFileSpec, 3, &selector, &value);
- if(err==noErr && selector)
- {
- NumToString(value, textStr);
- GetDItem(pDlog, kDBInfoSelector3Value, &itemType, &hDItem, &itemRect);
- SetIText(hDItem, textStr);
- textStr[0] = 4;
- BlockMove(&selector, &textStr[1], 4);
- }
- else
- {
- GetIndString(textStr, kDBInfoStrId, kStrNoInfo);
- }
- GetDItem(pDlog, kDBInfoSelector3, &itemType, &hDItem, &itemRect);
- SetIText(hDItem, textStr);
- // Mixin?
- Boolean isMixin = AGFileIsMixin(&guideFileSpec);
- GetIndString(textStr, kDBInfoStrId, (isMixin)?kStrYes:kStrNo);
- GetDItem(pDlog, kDBInfoMixin, &itemType, &hDItem, &itemRect);
- SetIText(hDItem, textStr);
- // Version
- AGFileMajorRevType majorRev;
- AGFileMinorRevType minorRev;
- err = AGFileGetDBVersion(&guideFileSpec, &majorRev, &minorRev);
- if(err==noErr)
- {
- Str255 majorRevStr;
- Str255 minorRevStr;
- Str255 dotStr;
- NumToString((long)majorRev, majorRevStr);
- NumToString((long)minorRev, minorRevStr);
- GetIndString(dotStr, kDBInfoStrId, kStrDot);
- // PLstrcpy(textStr, majorRevStr)
- BlockMoveData(majorRevStr, textStr, majorRevStr[0]+1);
- // PLstrcat(textStr, dotStr)
- BlockMoveData(&dotStr[1], &textStr[textStr[0]+1], dotStr[0]);
- textStr[0] += dotStr[0];
- // PLstrcat(textStr, minorRevStr)
- BlockMoveData(&minorRevStr[1], &textStr[textStr[0]+1], minorRevStr[0]);
- textStr[0] += minorRevStr[0];
- GetDItem(pDlog, kDBInfoVersion, &itemType, &hDItem, &itemRect);
- SetIText(hDItem, textStr);
- }
- // Script and Region
- AGFileDBScriptType script;
- AGFileDBRegionType region;
- err = AGFileGetDBCountry(&guideFileSpec, &script, ®ion);
- if(err==noErr)
- {
- NumToString((long)script, textStr);
- GetDItem(pDlog, kDBInfoScript, &itemType, &hDItem, &itemRect);
- SetIText(hDItem, textStr);
- NumToString((long)region, textStr);
- GetDItem(pDlog, kDBInfoRegion, &itemType, &hDItem, &itemRect);
- SetIText(hDItem, textStr);
- }
- // Show dialog.
- short itemHit;
- CenterWindow(pDlog);
- SetPort(pDlog);
- ShowWindow(pDlog);
- // Draw default outline around OK button.
- GetDItem(pDlog, kDBInfoOK, &itemType, &hDItem, &itemRect);
- PenSize(3,3);
- InsetRect(&itemRect, -4, -4);
- FrameRoundRect(&itemRect, 16, 16);
- PenNormal();
- // Let user read.
- while (isShowing) {
- ModalDialog(nil, &itemHit);
- isShowing = itemHit!=kDBInfoOK;
- }
- DisposeDialog(pDlog);
- }
- SetPort(pOldPort);
- }
-
- // ------------------------------------------------------------------------
- // TApp::DoGoAway
- //
- // This is the close side of TApp::ShowArt, ShowClipboard, ShowFeedback.
- //
- void
- TApp::DoGoAway()
- {
- // Clear our local document record if
- // it's object is going away.
- if(this->fCurDoc==this->fDocClip)
- {
- this->fDocClip = nil;
- this->fScrap->SetDoc(nil);
- }
- // Inherit go-away action from TApplication
- TApplication::DoGoAway();
- }
-
- // ------------------------------------------------------------------------
- void
- TApp::DoHighLevelEvent()
- {
- OSErr err = AEProcessAppleEvent(&this->fTheEvent);
- }
-
- // ------------------------------------------------------------------------
- // TApp::DoIdle
- // Do our idle and deferred events.
- //
- // AutoStart keeps track of whether or not guide was ever provided.
- // The fQuitAfterGuide flag automatically terminates this
- // application when the guide database closes.
- //
- void
- TApp::DoIdle()
- {
- // Check for guide run/quit.
- if(this->fAutoStart)
- if(this->fAutoStart->ShouldWeQuit())
- this->ExitLoop();
- // Update the scrap.
- if(this->fScrap)
- this->fScrap->DoIdle();
- }
-
- // ------------------------------------------------------------------------
- // TApp::DoMenuCommand
- // This is called when an item is chosen from the menu bar (after calling
- // MenuSelect or MenuKey). It does the right thing for each command.
- void
- TApp::DoMenuCommand(short menuID, short menuItem) // override
- {
-
- Str255 daName;
- short daRefNum;
- FSSpec fileSpec;
-
- switch (menuID)
- {
- case mApple:
- switch ( menuItem )
- {
- case iAbout:// bring up alert for About
- this->DoAbout();
- break;
- default: // all non-About items in this menu are DAs et al
- GetItem(GetMHandle(mApple), menuItem, daName);
- daRefNum = OpenDeskAcc(daName);
- break;
- } // switch
- break;
- case mFile:
- switch ( menuItem )
- {
- case iOpenFile:
- // User selects desired database.
- // Tell Apple Guide to open it..
- if(this->SelectFile(fileSpec)==noErr)
- AlertIfError(this->OpenGuideDatabase(&fileSpec));
- break;
- case iCloseFile:
- AlertIfError(AGClose(&this->fGuideRefNum));
- break;
- case iGetInfo:
- if(this->SelectFile(fileSpec)==noErr)
- this->DoDBInfoDialog(fileSpec);
- break;
- case iQuit:
- this->ExitLoop();
- break;
- default:
- break;
- } // switch
- break;
- case mEdit:
- switch ( menuItem )
- {
- case iCopy:
- this->CopyToClipboard();
- break;
- case iShowClipboard:
- this->ShowClipboard();
- break;
- default:
- break;
- } // switch
- break;
- default:
- break;
- } // switch
- // Turn off menu hilite.
- HiliteMenu(0);
- } // DoMenuCommand
-
- //-----------------------------------------------------------------------
- // TApp::EventLoop
- // We override the TApplication::EventLoop to add processing
- // of high-level events. While we're at it, since we're
- // System 7 only, we can always call WNE.
- //
- void
- TApp::EventLoop()
- {
- Boolean gotEvent;
- EventRecord tEvt;
- // call setup routine
- this->SetUp();
- // The loop
- while(!this->fDone)
- {
- this->SetDoc();
- gotEvent = WaitNextEvent(everyEvent, &tEvt, SleepVal(), this->fMouseRgn);
- this->fTheEvent = tEvt;
- if(!gotEvent)
- this->DoIdle();
- else // A real event
- {
- this->AdjustCursor();
- switch (fTheEvent.what)
- {
- case mouseDown:
- this->DoMouseDown();
- break;
-
- case mouseUp:
- this->DoMouseUp();
- break;
-
- case keyDown:
- case autoKey:
- this->DoKeyDown();
- break;
-
- case updateEvt:
- this->DoUpdateEvt();
- break;
-
- case diskEvt:
- this->DoDiskEvt();
- break;
-
- case activateEvt:
- this->DoActivateEvt();
- break;
-
- case osEvt:
- this->DoOSEvent();
- break;
-
- case kHighLevelEvent:
- this->DoHighLevelEvent();
- break;
-
- default:
- break;
-
- } // end switch (fTheEvent.what)
- }
- // update the cursor shape as needed after the event
- this->AdjustCursor();
- }
- // call cleanup handler
- this->CleanUp();
- }
-
-
- // ------------------------------------------------------------------------
- // TApp::GetVersion
- // Get the current version of the application.
- // Uses the long version string from 'vers' resource #1.
- //
- void
- TApp::GetVersion(Str255 versStr)
- {
- Handle hRes;
- char *pRes;
- short i;
-
- if (hRes = GetResource('vers', 1))
- {
- pRes = *hRes;
- pRes += 7 + pRes[6]; // long version pstring
- for(i=0; i<=pRes[0]; i++)
- versStr[i] = pRes[i]; // copy version pstring
- }
- }
-
- // ---------------------------------------------------------------------
- // TApp::OpenGuideDatabase
- // Open a guide database.
- // Return noErr if successful.
- // Update TApp database variables.
- //
- OSErr
- TApp::OpenGuideDatabase(FSSpec *pFileSpec)
- {
- OSErr result=noErr;
- if(gAGuideAvailable)
- {
- // Ask Apple Guide to open database.
- result = AGOpen(pFileSpec, 0, nil, &this->fGuideRefNum);
- }
- return result;
- }
-
- // ---------------------------------------------------------------------
- // TApp::Init
- // Do the things that our derived application class requires.
- // Basic initialization, before we start.
- // We store our application object in the core event handler
- // refCon so that the handler can use it. Avoids making it a global.
- // Return noErr if successful.
- OSErr
- TApp::Init()
- {
- OSErr err;
- SysEnvRec envRec;
- (void) SysEnvirons(curSysEnvVers, &envRec);
- // System 7 is required
- if(envRec.systemVersion<0x0700)
- {
- this->BigBadError(kUserStrId, kStrNotSevenOh);
- }
- // Our menuBar to use when we Start.
- this->fMenuBarID = rMenuBar;
- // Also clear our variables or we may get a bus error
- // at the first DoIdle (before we get the start event.)
- this->fDocClip = nil;
- this->fScrap = nil;
- this->fAutoStart = nil;
- // Install our core event handler.
- // We put the TApp object in the refCon.
- err = AEInstallEventHandler(kCoreEventClass,
- typeWildCard,
- #ifdef __powerc
- NewAEEventHandlerProc(TAppMo::HandleAECore),
- #else
- TApp::HandleAECore,
- #endif
- (long)this,
- kIsNotSysHandler);
- // Our custom event handler is installed in the derived class.
- // Starting is done in TApp::HandleAECore.
- // We wait until that happens before proceeding.
- this->fGuideRefNum = nil;
- // Check to see if the Apple Guide traps are available.
- long result=0;
- err = Gestalt(gestaltHelpMgrAttr, &result);
- gAGuideAvailable = (err==noErr && (result & (1 << gestaltAppleGuidePresent)));
- // Auto-Start object.
- this->fAutoStart = new TAStart;
- if(!this->fAutoStart)
- {
- return kErrNoAutoStartObj;
- }
- // Initialize the auto-start object.
- err = this->fAutoStart->Init();
- return err;
- }
-
- // ------------------------------------------------------------------------
- // TApp::Quit
- // We're quitting, so delete everything.
- // All of this probably goes away in the application heap anyway,
- // we're just being compulsively tidy.
- //
- void
- TApp::Quit()
- {
- SetCursor(*GetCursor(watchCursor));
- // Close the guide database and make Apple Guide quit.
- // Here's a case where we just do it without
- // any checking to see if a database is open or
- // Apple Guide is running. Nor do we check
- // for errors. The API should be robust enough to
- // handle all the possibilities without causing any problem.
- if(gAGuideAvailable)
- {
- (void) AGClose(&this->fGuideRefNum);
- (void) AGQuit();
- }
- // Remove our scrap object.
- if(this->fScrap)
- delete this->fScrap;
- // Remove our Auto-Start object.
- if(this->fAutoStart)
- delete this->fAutoStart;
- // Remove core event handler.
- (void) AERemoveEventHandler(kCoreEventClass,
- typeWildCard,
- kHandlerNotRequired,
- kIsNotSysHandler);
- SetCursor(&qd.arrow);
- }
-
- // ------------------------------------------------------------------------
- // TApp::SendEventToSelf
- // Our mechanism for full-factoring.
- //
- OSErr
- TApp::SendEventToSelf(AEEventID theEvent)
- {
- AppleEvent theMessage;
- AppleEvent theReply;
- OSErr err=noErr;
- // Make address to self.
- AEAddressDesc addrDesc;
- ProcessSerialNumber psn;
- psn.highLongOfPSN = 0;
- psn.lowLongOfPSN = kCurrentProcess;
- err = AECreateDesc(typeProcessSerialNumber, (Ptr) &psn,
- sizeof(psn), &addrDesc);
- if(err==noErr)
- {
- // Create AppleEvent for theMessage
- err = AECreateAppleEvent(kAEClassCustom,
- theEvent,
- &addrDesc, kAutoGenerateReturnID,
- kAnyTransactionID, &theMessage);
- if(err==noErr)
- {
- // Send message.
- err = AESend(&theMessage, &theReply,
- kAENoReply, kAEHighPriority,
- kNoTimeOut, nil, nil);
- // Clean-up
- (void) AEDisposeDesc(&theMessage);
- (void) AEDisposeDesc(&theReply);
- }
- (void) AEDisposeDesc(&addrDesc);
- }
- return err;
- }
-
- // ------------------------------------------------------------------------
- // TApp::SelectFile
- // Ask user for database file.
- // Dialog ID=rSelectFileDlog (OpenDLOG.rsrc)
- // contains a friendly prompt text line.
- // Return noErr if successful.
- //
- OSErr
- TApp::SelectFile(FSSpec& selectedFile)
- {
- OSErr err=noErr;
- Point where = {-1,-1};
- StandardFileReply reply;
- // Display both main and mixin files.
- short numTypes = 2;
- SFTypeList typeList = {kAGFileMain, kAGFileMixin, 0, 0};
- // Use custom dialog if available, otherwise use standard.
- Handle hDlog = GetResource('DLOG', rSelectFileDlog);
- if(hDlog!=nil && ResError()==noErr)
- {
- CustomGetFile(nil, numTypes, typeList, &reply,
- rSelectFileDlog, where,
- nil, nil, nil, nil, nil);
- }
- else
- {
- StandardGetFile(nil, numTypes, typeList, &reply);
- }
- if(reply.sfGood)
- {
- selectedFile = reply.sfFile;
- }
- else
- {
- selectedFile.name[0] = 0;
- err = kSelectFileCancel;
- }
- return err;
- }
-
- // ------------------------------------------------------------------------
- // TApp::SetDoc
- // Set the current window and document.
- //
- void
- TApp::SetDoc()
- {
- this->fWhichWindow = FrontWindow();
- if(this->fWhichWindow==nil)
- {
- // No window, default to the last window on the list.
- //this->fWhichWindow = *(WindowPtr*)WindowList;
- this->fCurDoc = nil;
- }
- else
- {
- this->fCurDoc = this->fDocList->FindDoc(this->fWhichWindow);
- SetPort(this->fWhichWindow);
- }
- }
-
- // ------------------------------------------------------------------------
- // TApp::ShowClipboard
- // Opens the clipboard window.
- // The document window is closed by the go-away box (TApp::DoGoAway).
- //
- void
- TApp::ShowClipboard()
- {
- if(this->fDocClip==nil)
- {
- // Clipboard window is not present.
- // Create a document and window for the clipboard.
- this->fDocClip = new TDocClip(kClipboardWinResID);
- if(this->fDocClip)
- {
- this->fDocList->AddDoc((TDocument*) this->fDocClip);
- // Set the clipboard document window's collaborator.
- this->fDocClip->SetScrapObj(this->fScrap);
- this->fDocClip->SetApp(this);
- // Set the document collaborator for the scrap object.
- this->fScrap->SetDoc(this->fDocClip);
- // Update current document and window pointer.
- this->fCurDoc = this->fDocClip;
- this->fWhichWindow = this->fCurDoc->GetDocWindow();
- SetPort(this->fWhichWindow);
- }
- }
- // Better show it, or at least bring it to the front.
- this->fDocClip->Show();
- // Invalidate window so that it will be updated and drawn.
- this->fDocClip->Invalidate();
- }
-
- // ---------------------------------------------------------------------
- // TApp::Start
- // Startup the application. Comes after the Init.
- // The Init is done in main. The Start comes with the oapp or odoc event.
- // Return noErr if successful.
- OSErr
- TApp::Start()
- {
- OSErr err=noErr;
- SetCursor(*GetCursor(watchCursor));
- // Install menus.
- Handle menuBar = GetNewMBar(this->fMenuBarID);
- if(!menuBar)
- {
- return kErrNoMenuBar;
- }
- SetMenuBar(menuBar); // Copy to current menu list.
- DisposHandle(menuBar); // Don't need it anymore.
- // Add DA names to Apple menu.
- AddResMenu(GetMHandle(mApple), 'DRVR');
- DrawMenuBar();
- // Scrap object
- this->fScrap = new TScrap;
- if(!this->fScrap)
- {
- return kErrNoScrapObject;
- }
- SetCursor(&qd.arrow);
- return err;
- }
-
- // =========================================================================
- // TAStart
- // ------------------------------------------------------------------------
- TAStart::TAStart()
- {
- // Guide collaborator.
- this->fGuideRefNum = nil;
- // Clear our flags.
- this->fGuideHasRun = false;
- this->fQuitAfterGuide = false;
- // The preset guide database file
- this->fPresetGuideFile.vRefNum = 0;
- this->fPresetGuideFile.parID = 0;
- this->fPresetGuideFile.name[0] = 0;
- }
-
- // ---------------------------------------------------------------------
- // TAStart::AttemptAutoStart
- // Start a guide database per the autoStart resource.
- // Return an error code if a self auto-start fails.
- // In all other cases, return noErr.
- // An alert is also given if a self auto-start fails.
- //
- // Given that enough startup information is provided,
- // the "autoStartFlag" flag determines whether or not the
- // auto-start is actually done.
- //
- // The following is always done, auto-start or not:
- // • The guide file spec (fPresetGuideFile) specified in the autoStart
- // resource will be saved for future use.
- // • The fQuitAfterGuide flag will be set to the resource field value.
- //
- AGErr
- TAStart::AttemptAutoStart()
- {
- AGErr result=noErr;
- Boolean okayToStart=false;
- // Default to this application's folder.
- this->fPresetGuideFile.vRefNum = -*(short*)LMGetSFSaveDisk();
- this->fPresetGuideFile.parID = *(long*)LMGetCurDirStore();
- this->fPresetGuideFile.name[0] = 0;
- // AutoStart resource?
- Handle hSpecRes = GetIndResource(kResAutoStart, 1);
- if(hSpecRes)
- {
- // We have an autoStart resource, get contents.
- HLock(hSpecRes);
- StartSpecPtr pStartSpec = (StartSpecPtr) *hSpecRes;
- // Set the quit-after-guide flag.
- this->fQuitAfterGuide = pStartSpec->quitAfterGuide;
- // Check for auto-start of self.
- if(pStartSpec->autoStartFlag==kAutoSelf)
- {
- // Auto-start self, get file spec for self.
- ProcessSerialNumber psn;
- OSErr err = GetCurrentProcess(&psn);
- if(err==noErr)
- {
- FSSpec appFile;
- ProcessInfoRec processInfo;
- processInfo.processInfoLength = sizeof(ProcessInfoRec);
- processInfo.processName = nil;
- processInfo.processAppSpec = &appFile;
- err = GetProcessInformation(&psn, &processInfo);
- if(err==noErr)
- {
- this->fPresetGuideFile = appFile;
- okayToStart = pStartSpec->autoStartFlag;
- }
- }
- }
- else
- {
- // Not a auto-start of self, get file name from resource.
- if(pStartSpec->fileName[0]>0)
- {
- // We have a file name, that has first priority.
-
- // PLstrcpy(this->fPresetGuideFile.name, pStartSpec->fileName)
- BlockMoveData(pStartSpec->fileName, this->fPresetGuideFile.name, pStartSpec->fileName[0]+1);
- // If autoStartFlag flag is set, do auto-start.
- okayToStart = pStartSpec->autoStartFlag;
- }
- else if(pStartSpec->type>0)
- {
- // Else, we have a guide file type, find a file of that type.
- {
- short vRefNum = (-*(short*)LMGetSFSaveDisk());
- long dirID = (*(long*)LMGetCurDirStore());
- Boolean wantMixin = false;
- short dbIndex = 1;
- if(AGFileGetIndDB(vRefNum, dirID,
- pStartSpec->type, wantMixin,
- dbIndex, &this->fPresetGuideFile)==noErr)
- {
- // Found a file of that type, start it.
- // If autoStartFlag flag is set, do auto-start.
- okayToStart = pStartSpec->autoStartFlag;
- }
- }
- }
- }
- HUnlock(hSpecRes);
- // We've setup fPresetGuideFile, let's see if it's okay to start.
- // No autostart if option key is down.
- union
- {
- KeyMap asMap;
- Byte asBytes[16];
- };
- GetKeys(asMap);
- Boolean optionKeyNotDown = !(asBytes[0x3A>>3]&(1<<(0x3A&0x07))?true:false);
- if(okayToStart && optionKeyNotDown)
- {
- if(!gAGuideAvailable)
- Alert(rAutoStartNeedAlrt, nil); // Need Apple Guide
- else
- {
- // Apple Guide is available and we want an auto-start.
- // Use topic ID if present, otherwise do general guide startup.
- if(pStartSpec->sequenceID)
- result = AGOpenWithSequence(&this->fPresetGuideFile,
- 0, nil,
- pStartSpec->sequenceID,
- &this->fGuideRefNum);
- else
- result = AGOpen(&this->fPresetGuideFile,
- 0, nil,
- &this->fGuideRefNum);
- // If a self auto-start failed, then we can't go any further.
- // Put up an alert.
- if(okayToStart==kAutoSelf)
- {
- if(result!=noErr || AGGetStatus()!=kAGIsActive)
- {
- // Give the all-purpose "beats me" auto-start alert.
- Alert(rAutoStartUnknownAlrt, nil);
- }
- } // if(okayToStart…
- } // else if(optionKeyNotDown…
- } // if(okayToStart…
- }
- return result;
- }
-
- // ------------------------------------------------------------------------
- // TAStart::Init
- // Initialize the TAStart object.
- // Return noErr if successful.
- //
- OSErr
- TAStart::Init()
- {
- return noErr;
- }
-
- // ------------------------------------------------------------------------
- // TAStart::ShouldWeQuit
- // Return true if we should quit.
- // We quit if guide has run
- // AND it isn't running now
- // AND fQuitAfterGuide is true.
- //
- Boolean
- TAStart::ShouldWeQuit()
- {
- Boolean result=false;
- // Check for guide run/quit.
- if(gAGuideAvailable)
- {
- if(AGGetStatus()==kAGIsSleeping || AGGetStatus()==kAGIsActive)
- this->fGuideHasRun = true;
- else
- result = (this->fGuideHasRun && this->fQuitAfterGuide);
- }
- return result;
- }
-
- // =========================================================================
- // TScrap
- // ------------------------------------------------------------------------
- TScrap::TScrap()
- {
- this->fLastScrapCount = 0;
- // Initialize our value for the scrap count.
- (void) this->Update();
- }
-
- // ------------------------------------------------------------------------
- // TScrap::DoIdle
- // Do any action required during the idle processing.
- //
- void
- TScrap::DoIdle()
- {
- // If the scrap is updated and the clipboard window
- // is showing, update/invalidate the clipboard window.
- if(this->Update())
- if(this->fDocClip)
- this->fDocClip->Invalidate();
- }
-
- // ------------------------------------------------------------------------
- // TScrap::Draw
- void
- TScrap::Draw(WindowPtr pWin)
- {
- SetPort(pWin);
- TextFont(monaco);
- TextSize(9);
- long offset;
- long scrapLen = GetScrap(nil, 'TEXT', &offset);
- if(scrapLen>0)
- {
- Handle hContent = NewHandle(scrapLen);
- if(hContent)
- {
- scrapLen = GetScrap(hContent, 'TEXT', &offset);
- HLock(hContent);
- TextBox(*hContent, scrapLen, &pWin->portRect, teFlushDefault);
- DisposeHandle(hContent);
- }
- }
- }
-
- // ------------------------------------------------------------------------
- // TScrap::Put
- // Put the contents of the handle into the scrap.
- // The handle is not disposed.
- //
- void
- TScrap::Put(Handle hToScrap)
- {
- if(hToScrap)
- {
- HLock(hToScrap);
- (void) ZeroScrap();
- (void) PutScrap(GetHandleSize(hToScrap), 'TEXT', *hToScrap);
- HUnlock(hToScrap);
- }
- }
-
- // ------------------------------------------------------------------------
- // TScrap::Update
- // Set the value of the last scrapCount.
- // Return true if it has changed.
- Boolean
- TScrap::Update()
- {
- Boolean hasChanged=false;
- PScrapStuff pScrapStuff = InfoScrap();
- if(pScrapStuff)
- {
- hasChanged = (pScrapStuff->scrapCount!=this->fLastScrapCount);
- this->fLastScrapCount = pScrapStuff->scrapCount;
- }
- return hasChanged;
- }
-
-